home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / kerberos / pc / krb_libk.lha / Lib / KRB / GETADTKT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-01  |  6.9 KB  |  241 lines

  1. /*
  2.  * $Source: /mit/kerberos/src/lib/krb/RCS/get_ad_tkt.c,v $
  3.  * $Author: jtkohl $
  4.  *
  5.  * Copyright 1986, 1987, 1988 by the Massachusetts Institute
  6.  * of Technology.
  7.  *
  8.  * For copying and distribution information, please see the file
  9.  * <mit-copyright.h>.
  10.  */
  11.  
  12. #ifndef lint
  13. static char *rcsid_get_ad_tkt_c =
  14. "$Header: get_ad_tkt.c,v 4.15 89/07/07 15:18:51 jtkohl Exp $";
  15. #endif /* lint */
  16.  
  17. #include <mit_copy.h>
  18. #include <krb.h>
  19. #include <des.h>
  20. #include <prot.h>
  21. #include <string.h>
  22.  
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <sys/socket.h>
  26. #include <errno.h>
  27.  
  28. /* use the bsd time.h struct defs for PC too! */
  29. #include <sys\types.h>
  30.  
  31. extern int krb_debug;
  32.  
  33. struct timeval tt_local = { 0, 0 };
  34.  
  35. int swap_bytes;
  36. unsigned long rep_err_code;
  37.  
  38. /*
  39.  * get_ad_tkt obtains a new service ticket from Kerberos, using
  40.  * the ticket-granting ticket which must be in the ticket file.
  41.  * It is typically called by krb_mk_req() when the client side
  42.  * of an application is creating authentication information to be
  43.  * sent to the server side.
  44.  *
  45.  * get_ad_tkt takes four arguments: three pointers to strings which
  46.  * contain the name, instance, and realm of the service for which the
  47.  * ticket is to be obtained; and an integer indicating the desired
  48.  * lifetime of the ticket.
  49.  *
  50.  * It returns an error status if the ticket couldn't be obtained,
  51.  * or AD_OK if all went well.  The ticket is stored in the ticket
  52.  * cache.
  53.  *
  54.  * The request sent to the Kerberos ticket-granting service looks
  55.  * like this:
  56.  *
  57.  * pkt->dat
  58.  *
  59.  * TEXT            original contents of    authenticator+ticket
  60.  *            pkt->dat        built in krb_mk_req call
  61.  * 
  62.  * 4 bytes        time_ws            always 0 (?)
  63.  * char            lifetime        lifetime argument passed
  64.  * string        service            service name argument
  65.  * string        sinstance        service instance arg.
  66.  *
  67.  * See "prot.h" for the reply packet layout and definitions of the
  68.  * extraction macros like pkt_version(), pkt_msg_type(), etc.
  69.  */
  70.  
  71. get_ad_tkt(service,sinstance,realm,lifetime)
  72.     char    *service;
  73.     char    *sinstance;
  74.     char    *realm;
  75.     int     lifetime;
  76. {
  77.     static KTEXT_ST pkt_st;
  78.     KTEXT pkt = & pkt_st;    /* Packet to KDC */
  79.     static KTEXT_ST rpkt_st;
  80.     KTEXT rpkt = &rpkt_st;    /* Returned packet */
  81.     static KTEXT_ST cip_st;
  82.     KTEXT cip = &cip_st;    /* Returned Ciphertext */
  83.     static KTEXT_ST tkt_st;
  84.     KTEXT tkt = &tkt_st;    /* Current ticket */
  85.     C_Block ses;                /* Session key for tkt */
  86.     CREDENTIALS cr;
  87.     int kvno;            /* Kvno for session key */
  88.     char lrealm[REALM_SZ];
  89.     C_Block key;        /* Key for decrypting cipher */
  90.     Key_schedule key_s;
  91.     long time_ws = 0;
  92.  
  93.     char s_name[SNAME_SZ];
  94.     char s_instance[INST_SZ];
  95.     int msg_byte_order;
  96.     int kerror;
  97.     char rlm[REALM_SZ];
  98.     char *ptr;
  99.  
  100.     unsigned long kdc_time;   /* KDC time */
  101.  
  102.     if ((kerror = krb_get_tf_realm(TKT_FILE, lrealm)) != KSUCCESS)
  103.     return(kerror);
  104.  
  105.     /* Create skeleton of packet to be sent */
  106.     (void) gettimeofday(&tt_local,(struct timezone *) 0);
  107.  
  108.     pkt->length = 0;
  109.  
  110.     /*
  111.      * Look for the session key (and other stuff we don't need)
  112.      * in the ticket file for krbtgt.realm@lrealm where "realm" 
  113.      * is the service's realm (passed in "realm" argument) and 
  114.      * lrealm is the realm of our initial ticket.  If we don't 
  115.      * have this, we will try to get it.
  116.      */
  117.     
  118.     if ((kerror = krb_get_cred("krbtgt",realm,lrealm,&cr)) != KSUCCESS) {
  119.     /*
  120.      * If realm == lrealm, we have no hope, so let's not even try.
  121.      */
  122.     if ((strncmp(realm, lrealm, REALM_SZ)) == 0)
  123.         return(AD_NOTGT);
  124.     else{
  125.         if ((kerror = 
  126.          get_ad_tkt("krbtgt",realm,lrealm,lifetime)) != KSUCCESS)
  127.         return(kerror);
  128.         if ((kerror = krb_get_cred("krbtgt",realm,lrealm,&cr)) != KSUCCESS)
  129.         return(kerror);
  130.     }
  131.     }
  132.     
  133.     /*
  134.      * Make up a request packet to the "krbtgt.realm@lrealm".
  135.      * Start by calling krb_mk_req() which puts ticket+authenticator
  136.      * into "pkt".  Then tack other stuff on the end.
  137.      */
  138.     
  139.     kerror = krb_mk_req(pkt,"krbtgt",realm,lrealm,0L);
  140.  
  141.     if (kerror)
  142.     return(AD_NOTGT);
  143.  
  144.     /* timestamp */
  145.     bcopy((char *) &time_ws,(char *) (pkt->dat+pkt->length),4);
  146.     pkt->length += 4;
  147.     *(pkt->dat+(pkt->length)++) = (char) lifetime;
  148.     (void) strcpy((char *) (pkt->dat+pkt->length),service);
  149.     pkt->length += 1 + strlen(service);
  150.     (void) strcpy((char *)(pkt->dat+pkt->length),sinstance);
  151.     pkt->length += 1 + strlen(sinstance);
  152.  
  153.     rpkt->length = 0;
  154.  
  155.     /* Send the request to the local ticket-granting server */
  156.     if (kerror = send_to_kdc(pkt, rpkt, realm)) return(kerror);
  157.  
  158.     /* check packet version of the returned packet */
  159.     if (pkt_version(rpkt) != KRB_PROT_VERSION )
  160.         return(INTK_PROT);
  161.  
  162.     /* Check byte order */
  163.     msg_byte_order = pkt_msg_type(rpkt) & 1;
  164.     swap_bytes = 0;
  165.     if (msg_byte_order != HOST_BYTE_ORDER)
  166.     swap_bytes++;
  167.  
  168.     switch (pkt_msg_type(rpkt) & ~1) {
  169.     case AUTH_MSG_KDC_REPLY:
  170.     break;
  171.     case AUTH_MSG_ERR_REPLY:
  172.     bcopy(pkt_err_code(rpkt), (char *) &rep_err_code, 4);
  173.     if (swap_bytes)
  174.         swap_u_long(rep_err_code);
  175.     return(rep_err_code);
  176.  
  177.     default:
  178.     return(INTK_PROT);
  179.     }
  180.  
  181.     /* Extract the ciphertext */
  182.     cip->length = pkt_clen(rpkt);       /* let clen do the swap */
  183.  
  184.     bcopy((char *) pkt_cipher(rpkt),(char *) (cip->dat),cip->length);
  185.  
  186. #ifndef NOENCRYPTION
  187.     /* Attempt to decrypt it */
  188.  
  189.     key_sched(cr.session,key_s);
  190.     if (krb_debug)  printf("About to do decryption ...");
  191.     pcbc_encrypt((C_Block *)cip->dat,(C_Block *)cip->dat,
  192.                  (long) cip->length,key_s,cr.session,0);
  193. #endif /* !NOENCRYPTION */
  194.     /* Get rid of all traces of key */
  195.     bzero((char *) cr.session, sizeof(key));
  196.     bzero((char *) key_s, sizeof(key_s));
  197.  
  198.     ptr = (char *) cip->dat;
  199.  
  200.     bcopy(ptr,(char *)ses,8);
  201.     ptr += 8;
  202.  
  203.     (void) strcpy(s_name,ptr);
  204.     ptr += strlen(s_name) + 1;
  205.  
  206.     (void) strcpy(s_instance,ptr);
  207.     ptr += strlen(s_instance) + 1;
  208.  
  209.     (void) strcpy(rlm,ptr);
  210.     ptr += strlen(rlm) + 1;
  211.  
  212.     lifetime = (unsigned long) ptr[0];
  213.     kvno = (unsigned long) ptr[1];
  214.     tkt->length = (int) ptr[2];
  215.     ptr += 3;
  216.     bcopy(ptr,(char *)(tkt->dat),tkt->length);
  217.     ptr += tkt->length;
  218.  
  219.     if (strcmp(s_name, service) || strcmp(s_instance, sinstance) ||
  220.         strcmp(rlm, realm))    /* not what we asked for */
  221.     return(INTK_ERR);    /* we need a better code here XXX */
  222.  
  223.     /* check KDC time stamp */
  224.     bcopy(ptr,(char *)&kdc_time,4); /* Time (coarse) */
  225.     if (swap_bytes) swap_u_long(kdc_time);
  226.  
  227.     ptr += 4;
  228.  
  229.     (void) gettimeofday(&tt_local,(struct timezone *) 0);
  230.     if (abs((int)(tt_local.tv_sec - kdc_time)) > CLOCK_SKEW) {
  231.         return(RD_AP_TIME);        /* XXX should probably be better
  232.                        code */
  233.     }
  234.  
  235.     if (kerror = save_credentials(s_name,s_instance,rlm,ses,lifetime,
  236.                   kvno,tkt,tt_local.tv_sec))
  237.     return(kerror);
  238.  
  239.     return(AD_OK);
  240. }
  241.